﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

namespace Sinc.ERP.Application;

/// <summary>
/// 业务日志服务 🧩
/// </summary>
[ApiDescriptionSettings(ApplicationConst.GroupName, Order = 100)]
public class BusinessLogService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<BusinessLog> _businessLogRep;
    private readonly ISqlSugarClient _sqlSugarClient;

    public BusinessLogService(SqlSugarRepository<BusinessLog> businessLogRep, ISqlSugarClient sqlSugarClient)
    {
        _businessLogRep = businessLogRep;
        _sqlSugarClient = sqlSugarClient;
    }

    /// <summary>
    /// 新增业务日志
    /// </summary>
    /// <param name="logContent"></param>
    /// <param name="logType"></param>
    /// <returns></returns>
    public async Task Create(string logContent, BusinessLogTypeEnum logType = BusinessLogTypeEnum.User)
    {
        var model = new BusinessLog(logContent, logType);
        await this._businessLogRep.AsInsertable(model).ExecuteCommandAsync();
    }

    /// <summary>
    /// 分页查询业务日志 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("分页查询业务日志")]
    [ApiDescriptionSettings(Name = "Page"), HttpPost]
    public async Task<SqlSugarPagedList<BusinessLogOutput>> Page(PageBusinessLogInput input)
    {
        input.Keyword = input.Keyword?.Trim();
        var query = _businessLogRep.AsQueryable()
            .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Content.Contains(input.Keyword) || u.IPAddress.Contains(input.Keyword))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Content), u => u.Content.Contains(input.Content.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.IPAddress), u => u.IPAddress.Contains(input.IPAddress.Trim()))
            .WhereIF(input.Type.HasValue, u => u.Type == input.Type)
            .Select<BusinessLogOutput>();
        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
    }

    /// <summary>
    /// 获取业务日志详情 ℹ️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取业务日志详情")]
    [ApiDescriptionSettings(Name = "Detail"), HttpGet]
    public async Task<BusinessLog> Detail([FromQuery] QueryByIdBusinessLogInput input)
    {
        return await _businessLogRep.GetFirstAsync(u => u.Id == input.Id);
    }

    /// <summary>
    /// 增加业务日志 ➕
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("增加业务日志")]
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    public async Task<long> Add(AddBusinessLogInput input)
    {
        var entity = input.Adapt<BusinessLog>();
        return await _businessLogRep.InsertAsync(entity) ? entity.Id : 0;
    }

    /// <summary>
    /// 更新业务日志 ✏️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("更新业务日志")]
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    public async Task Update(UpdateBusinessLogInput input)
    {
        var entity = input.Adapt<BusinessLog>();
        await _businessLogRep.AsUpdateable(entity)
        .ExecuteCommandAsync();
    }

    /// <summary>
    /// 删除业务日志 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("删除业务日志")]
    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
    public async Task Delete(DeleteBusinessLogInput input)
    {
        var entity = await _businessLogRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        await _businessLogRep.FakeDeleteAsync(entity);   //假删除
        //await _businessLogRep.DeleteAsync(entity);   //真删除
    }

    /// <summary>
    /// 批量删除业务日志 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("批量删除业务日志")]
    [ApiDescriptionSettings(Name = "BatchDelete"), HttpPost]
    public async Task<int> BatchDelete([Required(ErrorMessage = "主键列表不能为空")] List<DeleteBusinessLogInput> input)
    {
        var exp = Expressionable.Create<BusinessLog>();
        foreach (var row in input) exp = exp.Or(it => it.Id == row.Id);
        var list = await _businessLogRep.AsQueryable().Where(exp.ToExpression()).ToListAsync();

        return await _businessLogRep.FakeDeleteAsync(list);   //假删除
        //return await _businessLogRep.DeleteAsync(list);   //真删除
    }

    /// <summary>
    /// 导出业务日志记录 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("导出业务日志记录")]
    [ApiDescriptionSettings(Name = "Export"), HttpPost, NonUnify]
    public async Task<IActionResult> Export(PageBusinessLogInput input)
    {
        var list = (await Page(input)).Items?.Adapt<List<ExportBusinessLogOutput>>() ?? new();
        if (input.SelectKeyList?.Count > 0) list = list.Where(x => input.SelectKeyList.Contains(x.Id)).ToList();
        return ExcelHelper.ExportTemplate(list, "业务日志导出记录");
    }

    /// <summary>
    /// 下载业务日志数据导入模板 ⬇️
    /// </summary>
    /// <returns></returns>
    [DisplayName("下载业务日志数据导入模板")]
    [ApiDescriptionSettings(Name = "Import"), HttpGet, NonUnify]
    public IActionResult DownloadTemplate()
    {
        return ExcelHelper.ExportTemplate(new List<ExportBusinessLogOutput>(), "业务日志导入模板");
    }

    /// <summary>
    /// 导入业务日志记录 💾
    /// </summary>
    /// <returns></returns>
    [DisplayName("导入业务日志记录")]
    [ApiDescriptionSettings(Name = "Import"), HttpPost, NonUnify, UnitOfWork]
    public IActionResult ImportData([Required] IFormFile file)
    {
        lock (this)
        {
            var stream = ExcelHelper.ImportData<ImportBusinessLogInput, BusinessLog>(file, (list, markerErrorAction) =>
            {
                _sqlSugarClient.Utilities.PageEach(list, 2048, pageItems =>
                {
                    // 校验并过滤必填基本类型为null的字段
                    var rows = pageItems.Where(x =>
                    {
                        return x.Content.IsNotEmpty();
                    }).Adapt<List<BusinessLog>>();

                    var storageable = _businessLogRep.Context.Storageable(rows)
                        .SplitError(it => it.Item.IPAddress?.Length > 50, "IP地址长度不能超过50个字符")
                        .SplitInsert(_ => true)
                        .ToStorage();

                    if (rows.Any())
                    {
                        storageable.BulkCopy();
                        storageable.BulkUpdate();
                    }
                    // 标记错误信息
                    markerErrorAction.Invoke(storageable, pageItems, rows);
                });
            });

            return stream;
        }
    }
}
